home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Library / Manuels & Misc / Assembly / AOA.ZIP / CH18 / XWPATCH.ASM < prev   
Encoding:
Assembly Source File  |  1994-07-15  |  8.1 KB  |  345 lines

  1. ; XWPATCH.ASM
  2. ;
  3. ;    Usage:
  4. ;        XWPATCH    - must be in same directory as XWING.EXE
  5. ;
  6. ; This program executes the XWING.EXE program and patches it to avoid
  7. ; having to enter the password every time you run it.
  8. ;
  9. ; This program is intended for educational purposes only.
  10. ; It is a demonstration of how to write a semiresident program.
  11. ; It is not intended as a device to allow the piracy of commercial software.
  12. ; Such use is illegal and is punishable by law.
  13. ;
  14. ; This software is offered without warranty or any expectation of
  15. ; correctness.  Due to the dynamic nature of software design, programs
  16. ; that patch other programs may not work with slight changes in the
  17. ; patched program (XWING.EXE).  USE THIS CODE AT YOUR OWN RISK.
  18. ;
  19. ;----------------------------------------------------------------------------
  20.  
  21.  
  22. byp        textequ    <byte ptr>
  23. wp        textequ    <word ptr>
  24.  
  25. ; Put these segment definitions here so the UCR Standard Library will
  26. ; load after zzzzzzseg (in the transient section).
  27.  
  28. cseg        segment para public 'CODE'
  29. cseg        ends
  30.  
  31. sseg        segment    para stack 'STACK'
  32. sseg        ends
  33.  
  34. zzzzzzseg    segment    para public 'zzzzzzseg'
  35. zzzzzzseg    ends
  36.  
  37.         .286
  38.         include        stdlib.a
  39.         includelib    stdlib.lib
  40.         matchfuncs
  41.  
  42.  
  43. CSEG        segment    para public 'CODE'
  44.         assume    cs:cseg, ds:nothing
  45.  
  46.  
  47. ; CountJSCalls-    Number of times xwing calls the Joystick code before
  48. ; we patch out the password call.
  49.  
  50. CountJSCalls    dw    250
  51.  
  52.  
  53. ; PSP-    Program Segment Prefix.  Needed to free up memory before running
  54. ;    the real application program.
  55.  
  56. PSP        dw    0
  57.  
  58.  
  59.  
  60. ; Program Loading data structures (for DOS).
  61.  
  62. ExecStruct    dw    0            ;Use parent's Environment blk.
  63.         dd    CmdLine            ;For the cmd ln parms.
  64.         dd    DfltFCB
  65.         dd    DfltFCB
  66. LoadSSSP    dd    ?
  67. LoadCSIP    dd    ?
  68. PgmName        dd    Pgm
  69.  
  70. DfltFCB        db    3,"           ",0,0,0,0,0
  71. CmdLine        db    2, "  ", 0dh, 16 dup (" ")    ;Cmd line for program
  72. Pgm        db    "XWING.EXE",0
  73.  
  74.  
  75.  
  76.  
  77.  
  78.  
  79.  
  80. ;****************************************************************************
  81. ; XWPATCH begins here.  This is the memory resident part.  Only put code
  82. ; which which has to be present at run-time or needs to be resident after
  83. ; freeing up memory.
  84. ;****************************************************************************
  85.  
  86. Main        proc
  87.         mov    cs:PSP, ds
  88.         mov    ax, cseg        ;Get ptr to vars segment
  89.         mov    ds, ax
  90.  
  91.         mov    ax, zzzzzzseg
  92.         mov    es, ax
  93.         mov    cx, 1024/16
  94.         meminit2
  95.  
  96.  
  97. ; Now, free up memory from ZZZZZZSEG on to make room for XWING.
  98. ; Note: Absolutely no calls to UCR Standard Library routines from
  99. ; this point forward! (ExitPgm is okay, it's just a macro which calls DOS.)
  100. ; Note that after the execution of this code, none of the code & data
  101. ; from zzzzzzseg on is valid.
  102.  
  103.         mov    bx, zzzzzzseg
  104.         sub    bx, PSP
  105.         inc    bx
  106.         mov    es, PSP
  107.         mov    ah, 4ah
  108.         int    21h
  109.         jnc    GoodRealloc
  110.  
  111. ; Okay, I lied.  Here's a StdLib call, but it's okay because we failed
  112. ; to load the application over the top of the standard library code.
  113. ; But from this point on, absolutely no more calls!
  114.  
  115.         print
  116.         byte    "Memory allocation error."
  117.         byte    cr,lf,0
  118.         jmp    Quit
  119.  
  120. GoodRealloc:
  121.  
  122. ; Now load the XWING program into memory:
  123.  
  124.         mov    bx, seg ExecStruct
  125.         mov    es, bx
  126.         mov    bx, offset ExecStruct    ;Ptr to program record.
  127.         lds    dx, PgmName
  128.         mov    ax, 4b01h        ;Load, do not exec, pgm
  129.         int    21h
  130.         jc    Quit            ;If error loading file.
  131.  
  132. ; Unfortunately, the password code gets loaded dynamically later on.
  133. ; So it's not anywhere in memory where we can search for it.  But we
  134. ; do know that the joystick code is in memory, so we'll search for
  135. ; that code.  Once we find it, we'll patch it so it calls our SearchPW
  136. ; routine.  Note that you must use a joystick (and have one installed)
  137. ; for this patch to work properly.
  138.  
  139.         mov    si, zzzzzzseg
  140.         mov    ds, si
  141.         xor    si, si
  142.  
  143.         mov    di, cs
  144.         mov    es, di
  145.         mov    di, offset JoyStickCode
  146.         mov    cx, JoyLength
  147.         call    FindCode
  148.         jc    Quit            ;If didn't find joystick code.
  149.  
  150.  
  151. ; Patch the XWING joystick code here
  152.  
  153.         mov    byp ds:[si], 09ah    ;Far call
  154.         mov    wp ds:[si+1], offset SearchPW
  155.         mov    wp ds:[si+3], cs
  156.  
  157. ; Okay, start the XWING.EXE program running
  158.  
  159.         mov    ah, 62h            ;Get PSP
  160.         int    21h
  161.         mov    ds, bx
  162.         mov    es, bx
  163.         mov    wp ds:[10], offset Quit
  164.         mov    wp ds:[12], cs
  165.         mov    ss, wp cseg:LoadSSSP+2
  166.         mov    sp, wp cseg:LoadSSSP
  167.         jmp    dword ptr cseg:LoadCSIP
  168.  
  169.  
  170. Quit:        ExitPgm
  171.  
  172. Main        endp
  173.  
  174.  
  175. ; SearchPW gets call from XWING when it attempts to calibrate the joystick.
  176. ; We'll let XWING call the joystick several hundred times before we
  177. ; actually search for the password code.  The reason we do this is because
  178. ; XWING calls the joystick code early on to test for the presence of a
  179. ; joystick.  Once we get into the calibration code, however, it calls
  180. ; the joystick code repetitively, so a few hundred calls doesn't take
  181. ; very long to expire.  Once we're in the calibration code, the password
  182. ; code has been loaded into memory, so we can search for it then.
  183.  
  184. SearchPW    proc    far
  185.         cmp    cs:CountJSCalls, 0
  186.         je    DoSearch
  187.         dec    cs:CountJSCalls
  188.         sti            ;Code we stole from xwing for
  189.         neg    bx        ; the patch.
  190.         neg    di
  191.         ret
  192.  
  193. ; Okay, search for the password code.
  194.  
  195. DoSearch:    push    bp
  196.         mov    bp, sp
  197.         push    ds
  198.         push    es
  199.         pusha
  200.  
  201. ; Search for the password code in memory:
  202.  
  203.         mov    si, zzzzzzseg
  204.         mov    ds, si
  205.         xor    si, si
  206.  
  207.         mov    di, cs
  208.         mov    es, di
  209.         mov    di, offset PasswordCode
  210.         mov    cx, PWLength
  211.         call    FindCode
  212.         jc    NotThere        ;If didn't find pw code.
  213.  
  214.  
  215. ; Patch the XWING password code here.  Just store NOPs over the five
  216. ; bytes of the far call to the password routine.
  217.  
  218.         mov    byp ds:[si+11], 090h    ;NOP out a far call
  219.         mov    byp ds:[si+12], 090h
  220.         mov    byp ds:[si+13], 090h
  221.         mov    byp ds:[si+14], 090h
  222.         mov    byp ds:[si+15], 090h
  223.  
  224. ; Adjust the return address and restore the patched joystick code so
  225. ; that it doesn't bother jumping to us anymore.
  226.  
  227. NotThere:    sub    word ptr [bp+2], 5    ;Back up return address.
  228.         les    bx, [bp+2]        ;Fetch return address.
  229.  
  230. ; Store the original joystick code over the call we patched to this
  231. ; routine.
  232.  
  233.         mov    ax, word ptr JoyStickCode
  234.         mov    es:[bx], ax
  235.         mov    ax, word ptr JoyStickCode+2
  236.         mov    es:[bx+2], ax
  237.         mov    al, byte ptr JoyStickCode+4
  238.         mov    es:[bx+4], al
  239.  
  240.         popa
  241.         pop    es
  242.         pop    ds
  243.         pop    bp
  244.         ret
  245. SearchPW    endp
  246.  
  247. ;****************************************************************************
  248. ;
  249. ; FindCode: On entry, ES:DI points at some code in *this* program which
  250. ;        appears in the XWING game.  DS:SI points at a block of memory
  251. ;        in the XWING game.  FindCode searches through memory to find the
  252. ;        suspect piece of code and returns DS:SI pointing at the start of
  253. ;        that code.  This code assumes that it *will* find the code!
  254. ;        It returns the carry clear if it finds it, set if it doesn't.
  255.  
  256. FindCode    proc    near
  257.         push    ax
  258.         push    bx
  259.         push    dx
  260.  
  261. DoCmp:        mov    dx, 1000h        ;Search in 4K blocks.
  262. CmpLoop:      push    di            ;Save ptr to compare code.
  263.         push    si            ;Save ptr to start of string.
  264.         push    cx            ;Save count.
  265.     repe    cmpsb
  266.         pop    cx
  267.         pop    si
  268.         pop    di
  269.         je    FoundCode
  270.         inc    si
  271.         dec    dx
  272.         jne    CmpLoop
  273.         sub    si, 1000h
  274.         mov    ax, ds
  275.         inc    ah
  276.         mov    ds, ax
  277.         cmp    ax, 9000h        ;Stop at address 9000:0
  278.         jb    DoCmp            ; and fail if not found.
  279.  
  280.         pop    dx
  281.         pop    bx
  282.         pop    ax
  283.         stc
  284.         ret
  285.  
  286. FoundCode:    pop    dx
  287.         pop    bx
  288.         pop    ax
  289.         clc
  290.         ret
  291. FindCode    endp
  292.  
  293.  
  294. ;****************************************************************************
  295. ;
  296. ; Call to password code that appears in the XWING game.  This is actually
  297. ; data that we're going to search for in the XWING object code.
  298.  
  299. PasswordCode    proc    near
  300.         call    $+47h
  301.         mov    [bp-4], ax
  302.         mov    [bp-2], dx
  303.         push    dx
  304.         push    ax
  305.         byte    9ah, 04h, 00
  306. PasswordCode    endp
  307. EndPW:
  308.  
  309. PWLength    =    EndPW-PasswordCode
  310.  
  311.  
  312. ; The following is the joystick code we're going to search for.
  313.  
  314. JoyStickCode    proc    near
  315.         sti
  316.         neg    bx
  317.         neg    di
  318.         pop    bp
  319.         pop    dx
  320.         pop    cx
  321.         ret
  322.         mov    bp, bx
  323.         in    al, dx
  324.         mov    bl, al
  325.         not    al
  326.         and    al, ah
  327.         jnz    $+11h
  328.         in    al, dx
  329. JoyStickCode    endp
  330. EndJSC:
  331.  
  332. JoyLength    =    EndJSC-JoyStickCode
  333. cseg        ends
  334.  
  335. sseg        segment    para stack 'STACK'
  336.         dw    256 dup (0)
  337. endstk        dw    ?
  338. sseg        ends
  339.  
  340. zzzzzzseg    segment    para public 'zzzzzzseg'
  341. Heap        db    1024 dup (0)
  342. zzzzzzseg    ends
  343.  
  344.         end    Main
  345.